#include <iostream>
#include <limits>

using std::cout;
using std::endl;
using std::cin;

//复数i^2 = -1
class Complex
{
    friend Complex operator+(const Complex &lhs, const Complex &rhs);
public:
    Complex(double dreal = 0, double dimag = 0)
    : _dreal(dreal)
    , _dimag(dimag)
    {
        cout << "Complex(double = 0, double = 0)" << endl;
    }

    //以成员函数的形式进行重载
    //对于对象本身发生改变的这种运算符，一般建议使用成员函数
    //的形式进行重载
    //复合赋值运算符，+=、-=、*=、/=、%=、<<=、>>=
    Complex &operator+=(const Complex &rhs)
    {
        cout << "Complex &operator+=(const Complex &)" << endl;
        _dreal += rhs._dreal;
        _dimag += rhs._dimag;

        return *this;
    }

    //1、前置++比后置++的效率高，因为后置++函数在调用的时候，会有
    //拷贝构造函数的调用，会有局部对象的销毁，而函数调用是有开销的
    //2、前置++的返回值是一个左值，可以进行取地址；后置++的返回值
    //是一个右值，不能进行取地址
    Complex &operator++()
    {
        cout << "Complex &operator++()" << endl;
        ++_dreal;
        ++_dimag;

        return *this;
    }

    Complex operator++(int)//int只是一个标识，并不代表传参
    {
        cout << "Complex operator++(int)" << endl;
        Complex tmp(*this);//tmp是一个局部变量

        _dreal++;
        _dimag++;

        return tmp;
    }

    void print() const
    {
        /* cout << _dreal << " + " << _dimag << "i" << endl; */
        if(0 == _dreal && 0 == _dimag)
        {
            cout << 0 << endl;
        }
        else if(0 == _dreal)
        {
            cout << _dimag << "i" << endl;
        }
        else 
        {
            cout << _dreal;
            if(_dimag > 0)
            {
                cout << " + " << _dimag << "i" << endl;
            }
            else if(_dimag < 0)
            {
                cout << " - " << (-1) * _dimag << "i" << endl;
            }
            else
            {
                cout << endl;
            }
        }
    }

    //获取实部与虚部
    double getReal() const
    {
        return _dreal;
    }

    double getImag() const
    {
        return _dimag;
    }

    ~Complex()
    {
        cout << "~Complex()" << endl;
    }

    //如果将输出流运算符函数以成员函数的形式进行重载，那么就必须满足
    //两个参数的要求，所以需要将Complex类型的对象用this指针进行替代
    //但是这样就会改变流对象os与Complex对象的位置，这样就违背了
    //运算符重载的规则，不能改变操作的位置，所以就不能将输出流
    //运算符以成员函数的形式进行重载
    /* std::ostream &operator<<(std::ostream &os);//error */
    friend std::ostream &operator<<(std::ostream &os, const Complex &rhs);
    friend std::istream &operator>>(std::istream &is, Complex &rhs);

private:
    double _dreal;
    double _dimag;
};


//对于运算符重载而言，要确定函数的名字（这个比较简单），然后需要
//确定函数的参数列表，最后确定函数的返回类型
//3、运算符重载的第三种形式：运算符重载之友元函数
Complex operator+(const Complex &lhs, const Complex &rhs)
{
    cout << "friend Complex operator+(const Complex &, const Complex &)" << endl;
    return Complex(lhs._dreal + rhs._dreal, lhs._dimag + rhs._dimag);
}

std::ostream &operator<<(std::ostream &os, const Complex &rhs)
{
    cout << "std::ostream &operator<<(std::ostrstream &, const Complex &)" << endl;
    if(0 == rhs._dreal && 0 == rhs._dimag)
    {
        os << 0 << endl;
    }
    else if(0 == rhs._dreal)
    {
        os << rhs._dimag << "i" << endl;
    }
    else 
    {
        os << rhs._dreal;
        if(rhs._dimag > 0)
        {
            os << " + " << rhs._dimag << "i" << endl;
        }
        else if(rhs._dimag < 0)
        {
            os << " - " << (-1) * rhs._dimag << "i" << endl;
        }
        else
        {
            os << endl;
        }
    }

    return os;
}

void readDouble(std::istream &is, double &number)
{

    while(is >> number, !is.eof())
    {
        if(is.bad())
        {
            std::cerr << "The istream is bad" << endl;
            return;
        }
        else if(is.fail())
        {
            is.clear();//重置流的状态
            is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清空缓冲区
            cout << "pls input double data" << endl;
        }
        else
        {
            cout << "number = " << number << endl;
            break;
        }
    }
}

std::istream &operator>>(std::istream &is, Complex &rhs)
{
    cout << "std::istream &operator>>(std::istream &, Complex &)" << endl;
    /* is >> rhs._dreal >> rhs._dimag; */
    readDouble(is, rhs._dreal);
    readDouble(is, rhs._dimag);

    return is;
}

void test()
{
    Complex c1(1, 2);
    cout << "c1 = ";
    c1.print();

    cout << endl;
    Complex c2(3, 4);
    cout << "c2 = ";
    c2.print();

    cout << endl;
    Complex c3 = c1 + c2;
    cout << "c3 = ";
    c3.print();
}

void test2()
{
    int a = 10;
    int b = 20;
    b += a;

    cout << endl;
    Complex c1(1, 2);
    cout << "c1 = ";
    c1.print();

    cout << endl;
    Complex c2(3, 4);
    cout << "c2 = ";
    c2.print();

    cout << endl;
    c2 += c1;//c2 = 4 + 6i
    c2.operator+=(c1);
    cout << "c2 = ";
    c2.print();
}

void test3()
{
    int a = 10;
    cout << "表达式的值 = " << (a++)  << ", a = " << a << endl;//表达式的值 10, a = 11 
    cout << "表达式的值 " << ++a << ", a = " << a << endl;//表达式 =12，a = 12

    cout <<endl;
    Complex c1(1, 2);
    cout << "c1 = ";
    c1.print();

    cout << endl << "对c1执行前置++与后置++" << endl;
    cout << "(++c1) = ";
    (++c1).print();
    cout << "c1 = ";
    c1.print();

    cout << endl;
    cout << "(c1++) = ";
    (c1++).print();
    cout << "c1 = ";
    c1.print();

    &(++c1);
    /* &(c1++);//error */
}

void test4()
{
    Complex c1(1, 2);
    cout << "c1 = ";
    c1.print();

    cout << endl << endl;
    Complex c2(1, 0);
    cout << "c2 = ";
    c2.print();

    cout << endl << endl;
    Complex c3(1, -2);
    cout << "c3 = ";
    c3.print();

    cout << endl << endl;
    Complex c4(0, 2);
    cout << "c4 = ";
    c4.print();

    cout << endl << endl;
    Complex c5(0, 0);
    cout << "c5 = ";
    c5.print();

    cout << endl << endl;
    Complex c6(0, -2);
    cout << "c6 = ";
    c6.print();

    cout <<endl << endl;
    Complex c7(-1, 2);
    cout << "c7 = ";
    c7.print();

    cout << endl << endl;
    Complex c8(-1, 0);
    cout << "c8 = ";
    c8.print();

    cout << endl << endl;
    Complex c9(-1, -2);
    cout << "c9 = ";
    c9.print();
}

void test5()
{
    Complex c1(1, 2);
    cout << "c1 = " << c1 << endl;
    /* cout << "c1 = " << c1 << endl */ 
    /*     << 1 << 2 << "hello" << endl << c1 << endl;//简写,链式编程 */
    /* operator<<(cout, "c1 = "); */
    /* operator<<(operator<<(cout, "c1 = "), c1); */
    /* cout.operator<<(endl); */
    /* operator<<(operator<<(cout, "c1 = "), c1).operator<<(endl);//还原 */

    cout << endl;
    Complex c2;
    cin >> c2;
    cout << "c2 = " << c2 << endl;
}

int main(int argc, char **argv)
{
    test5();
    return 0;
}



